package testCase;

import junit.framework.TestCase;
import static org.junit.Assert.*;
import java.lang.reflect.*;
import java.util.Random;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class testField extends TestCase {
	private main.Field field;
	
	
	@Before
	public void setUp() {
		field = new main.Field();
	}
	
	@After
	public void tearDown() {
		// Teardown for data used by the unit tests
	}
	
	@Test
	public void testGetHeight() {
		int result;
		result = field.getHeight();
		assertEquals(result, 8);
	}
	
	@Test
	public void testGetWidth() {
		int result;
		result = field.getWidth();
		assertEquals(result, 8);
	}
	
	@Test
	public void testGetCell() {
		AccessPrivate newHacker = new AccessPrivate();
		int[][] expectedField;
		int[][] testField = new int [8][8];
		try { 
		     expectedField = newHacker.reflectField();
		     for (int i = 0; i < field.getHeight(); i++) {
		    	 for (int j = 0; j < field.getWidth(); j++) {
		    		 testField[i][j] = field.getCell(i, j);
		    	 }
		     }
		     assertArrayEquals(expectedField, testField);
		}
		catch (Exception e) {
		     e.printStackTrace();
		}
	}
	
	@Test
	/**
	 * This check the coordinate (0,0) is is clicked
	 */
	public void testIsClicked1() {
		int x1 = 0, y1 = 0;  //(0,0)
		field.clickOn(x1, y1);// click (0,0)
		boolean test = field.isClicked(x1, y1); //return true if (0,0) clicked
		assertTrue(test);
	}
	
	@Test
	/**
	 * check the coordinate (1,7) is clicked
	 */
	public void testIsClicked2() {
		int x2 = 1, y2 = 7;  //(1,7)
		boolean test = (field.isEmpty(x2, y2) == false); //return true if (1,7) havn't been clicked
		assertTrue( test);
	}
	
	@Test
	public void testClickOn() {
		Random rnd = new Random();
		int x = rnd.nextInt(field.getHeight());
		int y = rnd.nextInt(field.getWidth());
		while (field.isClicked(x, y)) {
			x = rnd.nextInt(field.getHeight());
			y = rnd.nextInt(field.getWidth());
		}
		field.clickOn(x, y);
		assertTrue(field.isClicked(x, y));
	}
	
	@Test
	public void testIsBomb() {
		int[][] expectedBombList = new int [10][2];
		int[][] testBombList = new int [10][2];
		int bombCount = 10;
		boolean result = true;
		int height = field.getHeight();
		int width = field.getWidth();
		for (int i = 0; i < height; i++) {
			for (int j = 0; j < width; j++) {
				if (field.getCell(i, j) == -1 && bombCount > 0) {
					expectedBombList[10-bombCount][0] = i;
					expectedBombList[10-bombCount][1] = j;
				}
				if (field.isBomb(i, j) && bombCount > 0) {
					testBombList[10-bombCount][0] = i;
					testBombList[10-bombCount][1] = j;
				}
				bombCount--;
			}
		}
		for (int i = 0; i < 10; i++) {
			if (expectedBombList[0][0] != testBombList[0][0] &&
				expectedBombList[0][1] != testBombList[0][1]) {
				result = false;
			}
		}
		assertTrue(result);
	}
	
	//@Test
	/**
	 * test if (0,2) is empty
	 */
	public void testIsEmpty1() {
		int x1 = 1, y1 = 7; //(0,2) is bomb
		boolean test = field.isEmpty(x1, y1); 
		assertTrue(test);
	}
	//@Test
		public void testIsEmpty2() {
			int x1 = 0, y1 = 0; //(0,0) is empty
			boolean test = (field.isEmpty(x1, y1) == true); 
			assertTrue(test);
		}
	//@Test
	//public void testInsertMines() {
		
	//}
	
	private class AccessPrivate {
		private int index;
		private int[][] privateField = new int[8][8];
		
		public int[][] reflectField() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		    main.Field instance = new main.Field();
		    Class secretClass = instance.getClass();
		    
		    Field fields[] = secretClass.getDeclaredFields();
		    
		    for (int i = 0; i < fields.length; i++){
		    	if (fields[i].getName() == "field") {
		    		index = i;
		    		fields[i].setAccessible(true);
		    		break;
		    	}
			}
		    
		    privateField = (int[][]) fields[index].get(instance);
		    
		    return privateField;
		}
	}
}
